Simulate dead lock with sampfore slim

Dani_S 2,886 Reputation points
2024-05-02T08:41:24.51+00:00

Hi,

How I simulate deadlock with with this code?

  public async Task<string> GetSessionToken(string developmentApiKey)

  {

     

      await _semLock.WaitAsync();

      try

      {

        

          if (string.IsNullOrEmpty(developmentApiKey))

          {

              return null;

          }

          string sessionToken = null;

      

          // Not exists in DB

          MongoDB.Bson.BsonDocument sessionDocumentBsonDocument = MongoDbHelper.GetSessionTokenRecord(developmentApiKey);

          if (sessionDocumentBsonDocument == null)

          {

              var automationApiClient = new AutomationApiClient();

              sessionToken = await automationApiClient.PostExtLogin2($"{Constants.RequestBaseAddress}/api/GSPortal/PostExtLogin", developmentApiKey);

              if (string.IsNullOrEmpty(sessionToken) || sessionToken.Contains("token not available"))

              {

                  return null;

              }

              var isTokenActive = await automationApiClient.GetTokenActive($"{Constants.RequestBaseAddress}/api/GSPortal/GetTokenActive", sessionToken);

              if (isTokenActive)

              {                        

                  MongoDbHelper.InsertSessionTokenDocument(developmentApiKey, sessionToken);

                  return sessionToken;

              }

              return null;

          }

          // Exists in DB

          else

          {

            

              var sessionTokenIdEncriptedData = sessionDocumentBsonDocument.GetValue("SessionTokenId").AsString;

              sessionToken = AesHelper.Decrypt(sessionTokenIdEncriptedData);

              var automationApiClient = new AutomationApiClient();

              var isTokenActive = await automationApiClient.GetTokenActive($"{Constants.RequestBaseAddress}/api/GSPortal/GetTokenActive", sessionToken);

              if (isTokenActive) // Exists in DB and active

              {

                  return sessionToken;

              }

              else // Exists in DB and not active

              {

                  sessionToken = await automationApiClient.PostExtLogin2($"{Constants.RequestBaseAddress}/api/GSPortal/PostExtLogin", developmentApiKey);

                  if (string.IsNullOrEmpty(sessionToken) || sessionToken.Contains("token not available"))

                  {

                      return null;

                  }

                  isTokenActive = await automationApiClient.GetTokenActive($"{Constants.RequestBaseAddress}/api/GSPortal/GetTokenActive", sessionToken);

                  if (isTokenActive)

                  { 

                       MongoDbHelper.UpdateSessionRecord(sessionDocumentBsonDocument, developmentApiKey, sessionToken);

                       return sessionToken;

                  }

                  return null;

              }

          }

      }

      catch(Exception ex)

      {                

          return null;

      }

      finally

      {

          _semLock.Release();

      }

  }
.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,467 questions
{count} votes

Accepted answer
  1. Jiale Xue - MSFT 37,131 Reputation points Microsoft Vendor
    2024-05-02T12:34:14.59+00:00

    Hi @Dani_S , Welcome to Microsoft Q&A,

    To simulate a deadlock with the provided code, you can introduce a deadlock scenario by having two methods trying to acquire the same locks in a different order.

    Here's how you can do it:

    
    public async Task DeadlockSimulator()
    
    {
    
        var task1 = GetSessionToken("api_key_1");
    
        var task2 = GetSessionToken("api_key_2");
    
        await Task.WhenAll(task1, task2);
    
    }
    
    

    Now, if GetSessionToken method is modified slightly to release and acquire the semaphore in a different order, it will result in a deadlock:

    
    public async Task<string> GetSessionToken(string developmentApiKey)
    
    {
    
        await Task.Delay(100); // Simulating some asynchronous work
    
        await _semLock.WaitAsync();
    
        try
    
        {
    
            if (string.IsNullOrEmpty(developmentApiKey))
    
            {
    
                return null;
    
            }
    
            string sessionToken = null;
    
            // Not exists in DB
    
            // Mocking the scenario that this operation takes some time
    
            await Task.Delay(100);
    
            // Assume we have a race condition here and another thread acquired the lock
    
            // on the same semaphore but with different developmentApiKey
    
            // Simulating a long-running task which causes a deadlock
    
            await Task.Delay(500);
    
            return sessionToken;
    
        }
    
        finally
    
        {
    
            _semLock.Release();
    
        }
    
    }
    
    

    This modification will cause a deadlock because the first call to GetSessionToken will acquire the semaphore lock, then it will delay for 100ms before acquiring the lock again. The second call to GetSessionToken will be blocked by the first call to WaitAsync(), and then it will also try to acquire the lock on the semaphore, but it will be stuck waiting for the first call to release the lock. The first call will not release the lock until it completes, but it can't complete because it's waiting for the second call to release its lock. This is a classic deadlock scenario. Best Regards,

    Jiale


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment". 

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.
    0 comments No comments

0 additional answers

Sort by: Most helpful